using System;
using System.Collections.Generic;
using System.Text;
using RapidHDL.Fabric;

namespace RapidHDL
{
    public class TestMicroCore : RapidHardware
    {
        public override bool ConfigureSettings()
        {
            Settings.UseStart = false;
            Settings.BuildHardware = true;
            Settings.ForceBuildHardware = false;
            Settings.RunFromXilinx = true;
            Settings.ClockFrequency = 1;
            Settings.UseSDRAM = true;
            Settings.BuildRemote = false;
            return true;
        }
        
        MicroCoreComponent oMicroCore;
        MicroCoreTable oTable;

        public override bool GenerateStructure(TopLevelComponent TopLevelComponent)
        {
            TopLevelComponent.TestBusWrite.Join(0);

            oTable = new MicroCoreTable();

            MicroCoreOp oOp = oTable.AddOp("A");
            oOp.AddStateInstruction("S1");
            oOp.AddStateInstruction("S2");
            oOp.AddStateInstruction("S3");

            oOp = oTable.AddOp("B");
            oOp.AddStateInstruction("S3");
            oOp.AddStateInstruction("S2");
            oOp.AddStateInstruction("S1");

            oOp = oTable.AddOp("C");
            oOp.AddStateInstruction("S4");
            oOp.AddStateInstruction("S5");
            oOp.AddStateInstruction("S6");
            oOp.AddJumpInstruction("skip");
            oOp.AddStateInstruction("S7");
            oOp.AddStateInstruction("S8","skip");

            oOp = oTable.AddOp("D");
            oOp.AddStateInstruction("S1");
            oOp.AddStateInstruction("S2","lbl1");
            oOp.AddBranchInstruction("I1", "lbl2");
            oOp.AddStateInstruction("S3");
            oOp.AddJumpInstruction("lbl1");
            oOp.AddStateInstruction("S4","lbl2");
            oOp.AddStateInstruction("S5");
            oOp.AddStateInstruction("S6");
            oOp.AddBranchInstruction("I2", "lbl1");
            oOp.AddStateInstruction("S7");
            oOp.AddStateInstruction("S8");

            oTable.CompileROM();

            oMicroCore = new MicroCoreComponent(TopLevelComponent, "core", oTable, TopLevelComponent.MainClock, TopLevelComponent.MainReset);
            oMicroCore.AddSignalSources();
            return true;
        }

        public override bool ConfigureSignalViews(TopLevelComponent TopLevelComponent)
        {
            oMicroCore.AddSignalViews();
            return true;
        }

        private void Display(HardwareScript poScript, int piClockTime)
        {
            oMicroCore.SignalDisplay(poScript, piClockTime);
        }


        public override bool GenerateHardwareScripts()
        {
            HardwareScript oScript = HardwareScripts.NewScript("test");
            oScript.NoReset = false;

            const int CLOCKS = 40;
            for (int iClockTime = 0; iClockTime < CLOCKS; iClockTime++)
            {
                oMicroCore.SignalDisplay(oScript, iClockTime);
            }

            oMicroCore.SignalAddress(oScript, 1, oTable.Ops["A"].Address);
            oMicroCore.SignalAddress(oScript, 2, oTable.Ops["B"].Address);
            oMicroCore.SignalAddress(oScript, 7, oTable.Ops["C"].Address);
            oMicroCore.SignalAddress(oScript, 16, oTable.Ops["D"].Address);

            oMicroCore.SignalStatusBit(oScript, 24, "I1", 1);

            return true;
        }

    }
}
